package homework.score;

import homework.score.display.IPrinter;
import homework.score.display.ListPrinter;
import homework.score.display.TablePrinter;
import homework.score.system.*;
import homework.score.util.InputUtil;
import homework.score.util.ReflectionUtil;

import java.util.*;
import java.util.regex.Pattern;

public class Main {

    public static void main(String[] args) {

        ManagementSystem system = new ManagementSystem(createMenuTree());

        system.run();
    }

    public static INode createMenuTree() {
        INode exitCmd = new ExitCommandNode("退出", "退出系统");

        final Pattern pNumbers = Pattern.compile("^\\d+$");

        final IPrinter listPrinter = new ListPrinter();

        final IPrinter tablePrinter = new TablePrinter();


        INode studentInfoMenu = new MenuNode("学生资料", "学生资料管理",

            new CommandNode("录入学生信息", null) {

                private final Pattern pYesOrNo = Pattern.compile("^[yn]$|^$", Pattern.CASE_INSENSITIVE);

                @Override
                public void execute() {
                    String code = InputUtil.input("[?] 请输入学生学号: ", pNumbers, "[!] 学号无效");

                    ObjectStore<Student> store = ObjectStore.getInstance(Student.class);

                    Student oldStudent = store.getObject(code);

                    if (oldStudent == null) {
                        Student student = new Student(code);


                        InputUtil.inputBean(student, "[?] 请输入学生%s: ", "[!] 无效%s");

                        store.setObject(student.getId(), student);
                        System.out.println("[*] 学生信息成功");
                    } else {
                        System.out.printf("[!] 学号为%s的学生已存在\n", code);

                        String result = InputUtil.input("[?] 是否更新学生信息? [y/N]: ", pYesOrNo, "[!] 请输入y或n");

                        if (result.trim().toUpperCase().equals("Y")) {

                            InputUtil.inputBean(oldStudent, "[?] 请输入学生%s: ", "[!] 无效%s");

                            System.out.println("[*] 学生信息成功");
                        } else {
                            System.out.println("[*] 学生信息未更改");
                        }
                    }

                }
            },

            new CommandNode("列出学生信息", null) {

                @Override
                public void execute() {
                    System.out.println("[*] 结果");
                    System.out.println("********************\n");

                    List<Map<String, String>> studentsAttrs = new ArrayList<Map<String, String>>();
                    ObjectStore<Student> store = ObjectStore.getInstance(Student.class);

                    for (Student s : store.getObjects()) {
                        studentsAttrs.add(ReflectionUtil.getProperties(s));
                    }

                    tablePrinter.print(studentsAttrs);
                }
            },

            new CommandNode("删除学生信息", null) {

                @Override
                public void execute() {
                    String code = InputUtil.input("[?] 请输入要删除的学生学号: ");
                    ObjectStore<Student> store = ObjectStore.getInstance(Student.class);

                    if (pNumbers.matcher(code).matches()) {
                        Student student = ObjectStore.getInstance(Student.class).getObject(code);
                        if (student == null) {
                            System.out.println("[!] 没有该学生");
                        } else {
                            store.removeObject(student.getId());
                            System.out.println("[*] 删除成功");
                        }
                    } else {
                        System.out.println("[!] 学号无效");
                    }
                }
            }
        );


        INode scoreQueryMenu = new MenuNode("成绩查询", "学生成绩查询");

        scoreQueryMenu
            .addNode(new CommandNode("所有成绩", null) {
                @Override
                public void execute() {
                    ObjectStore<EnumScore> scoreStore = ObjectStore.getInstance(EnumScore.class);
                    ObjectStore<Student> store = ObjectStore.getInstance(Student.class);

                    Set<Map.Entry<String, EnumScore>> entries = scoreStore.getEntries();

                    List<Map<String, String>> data = new ArrayList<Map<String, String>>();

                    for (Map.Entry<String, EnumScore> entry : entries) {
                        String id = entry.getKey();
                        Student student = store.getObject(id);


                        if (student == null) {
                            scoreStore.removeObject(id);
                        } else {
                            Map<String, String> row = new HashMap<String, String>();

                            row.put("id", student.getId());
                            row.put("name", student.getName());

                            EnumScore scores = entry.getValue();
                            for (Course c : Course.values()) {
                                row.put(c.name(), String.valueOf(scores.getScore(c)));
                            }

                            row.put("SUM", String.format("%.2f", scores.sum()));
                            row.put("AVERAGE", String.format("%.2f", scores.average()));

                            data.add(row);
                        }
                    }

                    tablePrinter.print(data);
                }
            }).addNode(new CommandNode("按学号查找", null) {

                @Override
                public void execute() {
                    String id = InputUtil.input("[?] 输入学号: ", pNumbers, "[!] 无效学号格式");

                    EnumScore scores = ObjectStore.getInstance(EnumScore.class).getObject(id);

                    if (scores == null) {
                        System.out.println("[*] 没有该同学成绩记录");
                    } else {
                        Map<String, String> scoreMap = new HashMap<String, String>();

                        for (Course c : Course.values()) {
                            double v = scores.getScore(c);

                            if (v != -1) {
                                scoreMap.put(c.toString(), String.valueOf(v));
                            }
                        }

                        scoreMap.put("总分", String.valueOf(scores.sum()));
                        scoreMap.put("平均分", String.valueOf(scores.average()));

                        listPrinter.print(Collections.singletonList(scoreMap));
                    }

                }
            });


        INode studentScoreMenu = new MenuNode("成绩管理", "学生成绩管理");

        studentScoreMenu
            .addNode(new CommandNode("录入成绩", null) {
                @Override
                public void execute() {
                    String id = InputUtil.input("[?] 请输入要录入成绩的学生学号: ");

                    if (pNumbers.matcher(id).matches()) {
                        Student student = ObjectStore.getInstance(Student.class).getObject(id);
                        if (student == null) {
                            System.out.println("[!] 没有该学生");
                        } else {
                            EnumScore scores = new EnumScore();

                            for (Course c : Course.values()) {
                                double score = InputUtil.input(Double.class, "[?] 输入" + c + "成绩: ", "[!] 无效成绩");

                                scores.setScore(c, score);
                            }

                            ObjectStore.getInstance(EnumScore.class).setObject(id, scores);
                            System.out.println("[*] 成功");
                        }
                    } else {
                        System.out.println("[!] 学号无效");
                    }
                }
            }).addNode(scoreQueryMenu);


        INode root = new MenuNode("管理系统", "欢迎使用学生信息管理系统",
                studentInfoMenu, studentScoreMenu, exitCmd);

        return root;
    }
}
